Sistema de Nombrado en Java (JNDI) [Parte I]

Para recibir notificaciones de eventos, un oyente se registra con una fuente de evento. En JNDI, las fuentes de eventos implementan los interfaces EventContext o EventDirContext.

Para obtener una fuente de eventos, debemos buscarla usando el servicio de nombres/directorios. Es decir, realizamos un lookup() sobre un objeto que fuerce el resultado a un EventContext o EventDirContext.

Si el contexto soporta o no estos dos interfaces es opcional. Un contexto que no soporte ninguno de ellos no soportar� la notificaci�n de eventos.

Aqu� tenemos un ejemplo que busca un nombre desde el contexto inicial y lo fuerza a un EventDirContext.

// Get the EventDirContext for registering the listener
EventDirContext ctx = (EventDirContext)
    (new InitialDirContext(env).lookup("ou=People"));

Para obtener una fuente de evento para el propio contexto inicial, usamos un string vac�o como argumento para lookup(). Aqu� tenemos un ejemplo.

// Get the EventDirContext for registering the listener
EventDirContext ctx = (EventDirContext)
    (new InitialDirContext(env).lookup(""));

EventContext se ha pensado para aplicaciones que pueden nombrar al objeto interesado. Registramos un oyente para recibir notificaciones usando EventContext.addNamingListener().

Aqu� tenemos un ejemplo que registra un NamespaceChangeListener con un contexto.

// Get the EventContext for registering the listener
EventContext ctx = (EventContext)
    (new InitialContext(env).lookup("ou=People"));

// Create the listener
NamingListener listener = new SampleNCListener("nc1");

// Register the listener for namespace change events
ctx.addNamingListener("ou=Objects,cn=Rosanna Lee", 
    EventContext.ONELEVEL_SCOPE, listener);

Cuando ejecutemos este ejemplo, esperar� un minuto para que el programa principal (el oyente) pueda recibir notificaciones sobre un thread que se ha creado.

.�Fuente y �mbito

Al objeto nombrado por el par�metro name de addNamingListener() se le llama fuente. El segundo par�metro especificado es el �mbito.

El �mbito especifica si el oyente recibe notificaciones de uno de los siguientes.

Aqu� tenemos un ejemplo� que a�ade oyentes usando la misma fuente pero tres �mbitos diferentes.

// Get the EventContext for registering the listener
EventContext ctx = (EventContext)
    (new InitialContext(env).lookup("ou=People"));

String target = ...;

// Create the listeners
NamingListener oneListener = new SampleListener("ONELEVEL");
NamingListener objListener = new SampleListener("OBJECT");
NamingListener subListener = new SampleListener("SUBTREE");

// Register the listeners by using different scopes
ctx.addNamingListener(target, EventContext.ONELEVEL_SCOPE, oneListener);
ctx.addNamingListener(target, EventContext.OBJECT_SCOPE, objListener);
ctx.addNamingListener(target, entContext.SUBTREE_SCOPE, subListener);

Despu�s de registrar los oyentes, este programa crea un thread que hace cambios en el espacio de nombres del servidor LDAP. Hace cambios en la fuene, en el hijo de la fuene y en el nieto de la fuene. El oyente registrado para el �mbito del objeto recibir� las dos notificaciones de cambios aplicados a la fuente. El oyente registrado para el �mbito de un nivel no recibir� est�s dos notificaciones pero recibir� las notificaciones para los cambios aplicados a los hijos. El oyente registrado para el �mbito del sub�rbol recibir� las notificaciones de todos los cambios.

.�Registrando Errores

addNamingListener() puede lanzar una NamingException cuando encuentra un error mientras registra el oyente. Sin embargo, no hay garant�a de que los datos suministrados se verifiquen inmediatamente en el momento del registro. Por ejemplo, algunas verificaciones podr�an requerir posiblemente interacci�n con el servidor. Cuando en estos casos ocurre un error, el proveedor de servicios llamar� al m�todo namingExceptionThrown() del oyente para notificarle el problema. Por lo tanto la aplicaci�n debe estar preparada para manejar el error sin importarle si ocurre en el momento del registro o as�ncronamente en el c�digo del oyente.

.�Fuentes no Existentes

Algunos servicos/proveedores de servicios podr�an permitir el registro de fuentes no existentes. Es decir, en el ejemplo anterior, la entrada llamada target podr�a no existir necesariamente en el momento de llamar a addNamingListener().

Para chequear si esta caracter�stica est� soportada, usamos targetMustExist().

Aqu� tenemos un ejemplo.

// Get the event context for registering the listener
EventContext ctx = (EventContext)new InitialContext(env).lookup("");

// Create the listener
NamingListener listener = new MyListener();
String target = ...;

// Check whether the object exists so that you don't wait
// forever for nonexistent object
if (!ctx.targetMustExist()) {
    // Check that the object exists before continuing
    // If lookup fails, exception will be thrown and 
    // you would skip registration
    ctx.lookup(target);
}

// Register the listener
ctx.addNamingListener(target, EventContext.ONELEVEL_SCOPE, listener);

Este ejemplo no quiere registrase para un objeto ObjectChangeListener que no exista, por eso primero chequea si el contexto requiere que el objeto exista. Si el contexto no lo requiere, el programa realiza un lookup().

El ejemplo tambi�n usa un oyente que implementa NamespaceChangeListener para que podamos detectar cuando el objeto ha desaparecido, en qu� punto el oyente se lo notifica al usuario y se auto des-registra.

public void objectRemoved(NamingEvent evt) {
    System.out.println(">>> removed: " + evt.getOldBinding().getName());
    deregisterSelf(evt.getEventContext());
}
private void deregisterSelf(EventContext ctx) {
    System.out.println("Deregistering listener...");
    synchronized (ctx) {
	try {
	    ctx.removeNamingListener(this);
	} catch (NamingException e) {
	    System.out.println("Listener removal problem: " + e);
	}
    }
}

.�Usar Filtros de B�squeda

Si queremos ser m�s selectivos sobre los objetos en los que estamos interesados, podemos usar un filtro de b�squeda. El inteface EventDirContext contiene sobrecargas de addNamingListener() que aceptan filtros de b�squeda, de la misma forma que lo hacen los m�todos de b�squeda del interface DirContext.

Aqu� tenemos un ejemplo que registra inter�s s�lo en objetos que tengan la clase de objeto "javaobject".

// Get the EventDirContext for registering the listener
EventDirContext ctx = (EventDirContext)
    (new InitialDirContext(env).lookup("ou=People"));

// Create the listener
NamingListener listener = new SampleNCListener("nc1");

// Set up the search constraints
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
	    
// Register the listener for namespace change events for
// entries identified using a search filter.
// In this example, register interest in namespace changes to
// objects that have the object class "javaobject".
ctx.addNamingListener("cn=Rosanna Lee", "(objectclass=javaobject)", 
    constraints, listener);

El filtro s�lo se aplica a los objetos existentes y aquellos que empiecen a existir despu�s del registro.

.�Des-registro

Un oyente registrado se convierte en des-registrado de una estas formas.

  • Cuando se llama a Context.close() sobre la fuente del evento, cualquier oyente registrado ser� autom�ticamente des-registrado.
  • Cuando un oyente recibe una notificaci�n de error mediante namingExceptionThrown(), es des-registrado autom�ticamente.
  • Cuando un oyente es eliminado expl�citamente mediante una llamada a EventContext.removeNamingListener(), es des-registrado.

En la secci�n Fuentes no Existentes puedes ver un ejemplo de des-registro.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
SIGUIENTE ARTÍCULO